<template>
    <el-table v-if="table"
              v-loading="loading || state.loading"
              ref="multipleTable"
              style="width: 100%"
              tooltip-effect="dark"
              :data="state.dataList"
              :row-key="rowKey"
              @sort-change="sortChange"
              @selection-change="handleSelectionChange"
              row-class-name="group">
        <el-table-column v-if="selection" type="selection"
                         width="55" :selectable="selectable"/>
        <slot></slot>
    </el-table>
    <slot v-else :list="state.dataList"></slot>

    <pagination v-if="state.isPage && state.pagination?.total > 0"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                v-bind="state.pagination"/>
</template>

<script setup lang="ts">
import {useTable} from "@/Hooks/table";
import Pagination from './pagination.vue'

defineOptions({
    name: 'CustomTable'
});

const emit = defineEmits(['update:selection', 'refresh'])
const props = defineProps({
    fetchList: {
        type: Function,
        default: undefined
    },
    options: {
        type: Object,
        default: () => ({})
    },
    selection: {
        type: [Array, Boolean],
        default: false
    },
    disabledIds: {
        type: Array,
        default: () => ([])
    },
    rowKey: {
        type: String,
        default: 'id'
    },
    table: { //默认表格模式，也可以当分页用
        type: Boolean,
        default: true
    },
    immediate: { //是否在创建页面时即调用数据列表接口，默认为true
        type: Boolean,
        default: true
    },
    query: { // 查询条件表单对象
        type: Object,
        default: () => ({})
    },
    loading: {
        type: Boolean,
        default: false
    }
})

const selectable = (row: any) => {
    return !props.disabledIds.includes(row[props.rowKey])
}

const multipleTable = ref();
const state = reactive({
    loading: false,
    isPage: true,
    multipleSelection: [],
    queryForm: props.query,
    dataList: [],
    createdIsNeed: props.immediate,
    pageList: props.fetchList,
    ...props.options,
})

const {
    getTableData,
    sortChange,
    handleCurrentChange,
    handleSizeChange,
    handleSelectionChange
} = useTable(state)


// 匹配B是否跟A所有的Key的值一样，B>A
function matchObjects(A: any, B: any) {
    // 获取对象 A 的所有键
    const keysOfA = Object.keys(A);

    // 检查 B 是否包含 A 的所有键，并且这些键的值是否相同
    for (const key of keysOfA) {
        if (B[key] !== A[key]) {
            return false;
        }
    }

    return true;
}


/**
 * 监听props.query的变化，当query变化时，重新发起请求获取表格数据
 * 参数newVal是变化后的query值
 * 注意：当参数中包含keyword时，不应使用此监听器
 */
watch(() => props.query, (newVal: any) => {
    if (!matchObjects(newVal, state.queryForm)) {
        state.queryForm = Object.assign({}, state.queryForm, newVal);
        if (props.immediate && state.loading === false && getTableData) {
            getTableData(true);
        }
    }
})

// 监听 multipleSelection 的变化
watch(() => state.multipleSelection, (newVal: any) => {
    nextTick(() => {
        emit('update:selection', newVal);
    });
})

// 监听 dataList 的变化
watch(() => state.dataList, (newVal: any) => {
    if (state.loading === false) {
        nextTick(() => {
            emit('refresh', newVal, state);
        });
    }
})

//重置列表数据
const updateTableData = (data: any) => {
    state.loading = true;
    state.dataList = [...data];
    nextTick(() => {
        state.loading = false
    });
}

// 暴露变量
defineExpose({
    getTableData,
    updateTableData
});
</script>

<style lang="scss" scoped>

</style>
